#include <linux/module.h>
#include <linux/kernel.h> /* printk() */
#include <asm/uaccess.h> /* copy_from/to_user */
#include <linux/fs.h> /* file_operations */
#include <linux/miscdevice.h>
#include "CommandHandler.h"

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Ryan Welton <Ryan.G.Welton@gmail.com>");
MODULE_DESCRIPTION("Buggered Linux Device for exploitation");
MODULE_VERSION("1.3.3.7");

static int doNothingIntializer(void);

static int doNothingIntializer(){
 return 0;
}

CommandHandler handler = {
  .runHandler = &doNothingIntializer
};

ssize_t read_from_vuln_device(struct file *filp, char *buf, 
                       size_t count, loff_t *f_pos){
  return 0;
}

ssize_t write_to_vuln_device(struct file *filp, const char * buf, size_t count, loff_t *f_pos)
{
  int ret = copy_from_user(&handler,buf,sizeof(CommandHandler));
  if(ret){
    printk("Failed to copy %d bytes", ret);
    return ret;
  }
  return 0;
}

long device_ioctl(struct file *filp,
                  unsigned int cmd,
                  unsigned long arg)
{
  switch (cmd) {
    case RUN_COMMAND_HANDLER:
       handler.runHandler();
       break;
    default :
       printk("Unknown ioctl cmd: %d", cmd);
       return -1;
  }
  return 0;
}
/* Structure that declares the usual file */
/* access functions */
struct file_operations device_ops = {
  read: read_from_vuln_device,
  write: write_to_vuln_device,
  unlocked_ioctl: device_ioctl
};

/*
Create our misc device - a char device that doesn't fit into any other device class
http://stackoverflow.com/questions/18456155/what-is-the-difference-between-misc-drivers-and-char-drivers
*/
static struct miscdevice vuln_device = {
        minor: MISC_DYNAMIC_MINOR,
        name: "cmd_handler", // Name ourselves /dev/string_format
        fops: &device_ops, //Struct for the file ops handler
        mode: 666
};

static int __init mod_begin(void)
{
   int ret;
   ret = misc_register(&vuln_device);
   if(ret)
     printk("Failed to register misc device");
   else
     printk("Module successfully loaded");

   return ret;//A non 0 return means init_module failed; module can't be loaded.
}

static void __exit mod_exit(void)
{
  int ret = misc_deregister(&vuln_device);
  if(ret)
    printk("There was an error unregistering device");
}

module_init(mod_begin);
module_exit(mod_exit);
